#pragma once

#include <new>
#include <list>
#include <algorithm>
#include <iostream> //for dump()
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stack>

/*
//default tag is engine
#ifndef STL_MEMORY_TAG
#define STL_MEMORY_TAG TAG_COMMON
#endif

void *operator new( size_t s );
void operator delete( void *p );
void *operator new[]( size_t s );
void operator delete[]( void *p );

template <typename T> class od_allocator;
template <> class od_allocator<void>
{
public:
    typedef void* pointer;
    typedef const void* const_pointer;
    // reference to void members are impossible.
    typedef void value_type;
    template <class U>
        struct rebind { typedef od_allocator<U> other; };
};

namespace ss_alloc{
    inline void destruct(char *){}
    inline void destruct(wchar_t*){}
    template <typename T>
        inline void destruct(T *t){t->~T();}
} // namespace ss_alloc

template <typename T>
class od_allocator
{
public:
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    template <class U>
        struct rebind { typedef od_allocator<U> other; };

    od_allocator(){}
    pointer address(reference x) const {return &x;}
    const_pointer address(const_reference x) const {return &x;}
    pointer allocate(size_type size, od_allocator<void>::const_pointer hint = 0) const
    {
        return static_cast<pointer>(Mem_Alloc(size*sizeof(T),STL_MEMORY_TAG));
    }

    template <class U> od_allocator(const od_allocator<U>&){}
    od_allocator(const od_allocator<T>&){}
    void deallocate(pointer p, size_type n) const
    {
        Mem_Free(p);
    }
    void deallocate(void *p, size_type n) const
    {
        Mem_Free(p);
    }
    size_type max_size() const throw() {return size_t(-1) / sizeof(value_type);}
    void construct(pointer p, const T& val)
    {
        new(static_cast<void*>(p)) T(val);
    }
    void construct(pointer p)
    {
        new(static_cast<void*>(p)) T();
    }
    void destroy(pointer p){ss_alloc::destruct(p);}
    //static void dump() {mem_.dump();}
private:
};

template <typename T, typename U>
inline bool operator==(const od_allocator<T>&, const od_allocator<U>){return true;}

template <typename T, typename U>
inline bool operator!=(const od_allocator<T>&, const od_allocator<U>){return false;}




// For VC6/STLPort 4-5-3 see /stl/_alloc.h, line 464
// "If custom allocators are being used without member template classes support :
// user (on purpose) is forced to define rebind/get operations !!!"
#ifdef _WIN32
#define SS_ALLOC_CDECL __cdecl
#else
#define SS_ALLOC_CDECL
#endif

namespace std{
template <class _Tp1, class _Tp2>
inline od_allocator<_Tp2>& SS_ALLOC_CDECL
__stl_alloc_rebind(od_allocator<_Tp1>& __a, const _Tp2*)
{
    return (od_allocator<_Tp2>&)(__a);
}


template <class _Tp1, class _Tp2>
inline od_allocator<_Tp2> SS_ALLOC_CDECL
__stl_alloc_create(const od_allocator<_Tp1>&, const _Tp2*)
{
    return od_allocator<_Tp2>();
}

} // namespace std

//TODO: this string implementation will not use our memory manager!!
//std::basic_string<char,std::char_traits<char>,od_allocator<char>>
class std::string : public std::string{
public:
	std::string(){}
	std::string(const char *str):std::string(str){}
	std::string(const std::string &str):std::string(str){}
};

template<typename T>
class std::vector : public std::vector<T,od_allocator<T> >{
public:
};

template<typename T>
class std::list : public std::list<T,od_allocator<T> >{
public:
};

template<typename Kt,typename comp=std::less<Kt> >
class odSet : public std::set<Kt,comp,od_allocator<Kt> >{
public:
};

template<typename Kt,typename Dt,typename comp=std::less<Kt> >
class std::map : public std::map<Kt,Dt,comp,od_allocator<Kt> >{
public:
};

template<typename T>
class odStack : public std::stack<T>{
public:
};

inline void *operator new( size_t s ) {
	return Mem_ClearedAlloc(s,STL_MEMORY_TAG);
}
inline void operator delete( void *p ) {
	Mem_Free(p);
}
inline void *operator new[]( size_t s ) {
	return Mem_ClearedAlloc(s,STL_MEMORY_TAG);
}
inline void operator delete[]( void *p ) {
	Mem_Free(p);
}
*/